﻿using System;
using System.Collections.Generic;
using System.Linq;
using GC_FFW.BusinessEntities.Abstractions.Interfaces.Soccerfame;
using GC_FFW.BusinessEntities.Soccerfame;
using GC_FFW.Common.Constants.HTML;
using GC_FFW.SoccerfameParser.Abstractions.Adapters;
using GC_FFW.SoccerfameParser.Abstractions.Interfaces.Adapters;
using GC_FFW.SoccerfameParser.Abstractions.Interfaces.Factories;
using GC_FFW.SoccerfameParser.Abstractions.Managers;
using HtmlAgilityPack;

namespace GC_FFW.SoccerfameParser.Adapters
{
	public class FutureMatchAdapter : BaseAdapter, IFutureMatchAdapter
	{
		#region Contants

		private const string MATCH_TEAMS_DIV_ID = "matchTeams";
		private const string MATCH_TEAM_DIV_ATTRIBUTE_CLASS_VALUE = "matchTeam";

		private const string TEAM_MATCHES_DIV_PART_ID = "team_";
		private const string BOTH_TEAM_MATCHES_DIV_PART_ID = "team_both";

		private const string TEAM_MATCH_DIV_ATTRIBUTE_CLASS_VALUE = "matchesTable openMatch";

		private const string TEAM_MATCH_TOURNAMENT_TYPE_CONTAINER_ATTRIBUTE_CLASS_VALUE = "type11";
		private const string TEAM_MATCH_DATE_CONTAINER_ATTRIBUTE_CLASS_VALUE = "type12";
		private const string TEAM_MATCH_DATE__YEAR_CONTAINER_ATTRIBUTE_CLASS_VALUE = "type13";
		private const string TEAM_MATCH_HOME_TEAM_CONTAINER_ATTRIBUTE_CLASS_VALUE = "matchCountryOther tar";
		private const string TEAM_MATCH_RESULT_CONTAINER_ATTRIBUTE_CLASS_VALUE = "matchScore";
		private const string TEAM_MATCH_AWAY_TEAM_CONTAINER_ATTRIBUTE_CLASS_VALUE = "matchCountryOther";

		#endregion

		#region Constructors

		public FutureMatchAdapter(HtmlDocumentBaseManager htmlDocumentManager, ISoccerfameDataHelperFactory soccerfameDataHelperFactory)
			: base(htmlDocumentManager, soccerfameDataHelperFactory) { }

		#endregion

		#region IMatchAdapter Members

		public IHyperlink GetTeamInfo(string url, bool isHomeTeam)
		{
			var htmlDocument = HtmlDocumentManager.CreateHtmlDocument(url);
			if (htmlDocument == null) return null;

			var pageMainContent = htmlDocument.GetElementbyId(MATCH_TEAMS_DIV_ID);
			if (pageMainContent == null) return null;

			var teams = pageMainContent.ChildNodes.Where(cn => cn.Name == TagNames.DIVISION
					&& cn.Attributes[TagAttributes.CLASS] != null
					&& cn.Attributes[TagAttributes.CLASS].Value == MATCH_TEAM_DIV_ATTRIBUTE_CLASS_VALUE).ToList();
			if (teams.Count != 2) return null;

			var team = teams.ElementAt(isHomeTeam ? 0 : 1);

			var h4 = team.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.HEADER_4);
			var result = h4 != null
				? HtmlDocumentManager.GetHyperlink(h4.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR))
				: null;

			if (result != null && SoccerfameDataHelperFactory.TeamNamesService != null)
				result.Name = SoccerfameDataHelperFactory.TeamNamesService.GetValidName(result.Name);

			return result;
		}

		public IEnumerable<IMatch> GetMatches(string url, bool? isHomeTeam)
		{
			var htmlDocument = HtmlDocumentManager.CreateHtmlDocument(url);
			if (htmlDocument == null) return null;

			var pageMainContent = htmlDocument.GetElementbyId(MIDDLE_PAGE_DIV_ID);
			if (pageMainContent == null) return null;

			var teams = HtmlDocumentManager.FindNodesByPartId(pageMainContent, TEAM_MATCHES_DIV_PART_ID).ToList();
			if (teams.Count < 3) return null;

			return isHomeTeam.HasValue
				? GetTeamMatches(teams.ElementAt(isHomeTeam.Value ? 0 : 1))
				: GetBothTeamMatches(teams.FirstOrDefault(t => t.Id == BOTH_TEAM_MATCHES_DIV_PART_ID));
		}

		#endregion

		#region Internal Implementation

		private IEnumerable<IMatch> GetTeamMatches(HtmlNode node)
		{
			var result = new List<IMatch>();

			var matches = (HtmlDocumentManager.FindNodesByAttributeValue(node, TagAttributes.CLASS,
				TEAM_MATCH_DIV_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList();
			if (!matches.Any()) return result;

			matches.ForEach(m =>
			{
				var match = new Match();

				var data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_TOURNAMENT_TYPE_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
					match.TournamentType =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_HOME_TEAM_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
				{
					match.HomeTeam =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));
					if (match.HomeTeam != null && SoccerfameDataHelperFactory.TeamNamesService != null)
						match.HomeTeam.Name = SoccerfameDataHelperFactory.TeamNamesService.GetValidName(match.HomeTeam.Name);
				}

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_AWAY_TEAM_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
				{
					match.AwayTeam =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));
					if (match.AwayTeam != null && SoccerfameDataHelperFactory.TeamNamesService != null)
						match.AwayTeam.Name = SoccerfameDataHelperFactory.TeamNamesService.GetValidName(match.AwayTeam.Name);
				}

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_RESULT_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
					match.MatchResult =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_DATE_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				match.Date = HtmlDocumentManager.GetInnerTextDateTime(data);

				result.Add(match);
			});

			return result;
		}

		private IEnumerable<IMatch> GetBothTeamMatches(HtmlNode node)
		{
			var result = new List<IMatch>();

			var matches = (HtmlDocumentManager.FindNodesByAttributeValue(node, TagAttributes.CLASS,
				TEAM_MATCH_DIV_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList();
			if (!matches.Any()) return result;

			matches.ForEach(m =>
			{
				var match = new Match();

				var data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_TOURNAMENT_TYPE_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
					match.TournamentType =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_HOME_TEAM_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
				{
					match.HomeTeam =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));
					if (match.HomeTeam != null && SoccerfameDataHelperFactory.TeamNamesService != null)
						match.HomeTeam.Name = SoccerfameDataHelperFactory.TeamNamesService.GetValidName(match.HomeTeam.Name);
				}

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_AWAY_TEAM_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
				{
					match.AwayTeam =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));
					if (match.AwayTeam != null && SoccerfameDataHelperFactory.TeamNamesService != null)
						match.AwayTeam.Name = SoccerfameDataHelperFactory.TeamNamesService.GetValidName(match.AwayTeam.Name);
				}

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_RESULT_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				if (data != null)
					match.MatchResult =
						HtmlDocumentManager.GetHyperlink(data.ChildNodes.FirstOrDefault(cn => cn.Name == TagNames.ANCHOR));

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_DATE_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				match.Date = HtmlDocumentManager.GetInnerTextDateTime(data);

				data = (HtmlDocumentManager.FindNodesByAttributeValue(m,
					TagAttributes.CLASS, TEAM_MATCH_DATE__YEAR_CONTAINER_ATTRIBUTE_CLASS_VALUE) ?? new List<HtmlNode>()).ToList()
					.FirstOrDefault();
				match.Date = new DateTime(HtmlDocumentManager.GetInnerTextInt(data), match.Date.Month, match.Date.Day);

				result.Add(match);
			});

			return result;
		}

		#endregion
	}
}
